# -*- coding: utf-8 -*-
import os
import shutil
import logging

import tempfile
import threading

from functools import wraps
from cStringIO import StringIO

import Image, ImageDraw, ImageFile, ImageFilter
ImageFile.MAXBLOCK = 2**20

from Monitor import getMonitors, Monitor

lock = threading.Lock()
def locked(fn):
	@wraps(fn)
	def wrapper(*args, **kwargs):
		with lock:
			return fn(*args, **kwargs)

	return wrapper

class Desktop(object):
	"""
	Represents the desktop

	:param config: The :mod:`ConfigParser` object
	"""
	
	def __init__(self, config):
		self.config = config

		if self.config.has_section('global'):
			self.Blending = self.config.getboolean('global', 'Blending')
			self.BlendRatio = self.config.getfloat('global', 'BlendRatio')
			self.Crop = self.config.getboolean('global', 'Crop')
			self.Fill = self.config.getboolean('global', 'Fill')
			self.Gradient = self.config.getboolean('global', 'Gradient')
			self.PreRotate = self.config.getboolean('global', 'PreRotate')
			self.Spanning = self.config.getboolean('global', 'Spanning')
			self.StackMode =  self.config.getboolean('global', 'StackMode')

		self.monitors = []
		self.wSize = None

		self.bgColour = (0, 0, 0)
		self.bgImage = None
		self.setMonitorExtents()
		self.createEmptyWallpaper()

	def loadCurrentWallpaper(self):
		pass
	
	def setWallpaperStyleSingle(self):
		pass

	def setWallpaperStyleMulti(self):
		pass
				
	def setWallPaperFromBmp(self, pathToBmp):
		pass
		
	def setWallpaper(self):
		pass
		
	def calcWallSize(self):
		"""
		Work out the size and ordering of the monitors
		"""
		# Also sets the relative offsets for building the wallpaper...
		ms = self.monitors

		primaryMonitor = [m for m in ms if m.isPrimary][0]

		leftMonitors = sorted([m for m in ms if m.left < 0])
		rightMonitors = sorted([m for m in ms if m.left >= primaryMonitor.right])
		topMonitors = sorted([m for m in ms if m.top < 0])
		bottomMonitors = sorted([m for m in ms if m.top >= primaryMonitor.bottom])

		hMonitors = [primaryMonitor,] + rightMonitors + leftMonitors
		vMonitors = [primaryMonitor,] + bottomMonitors + topMonitors

		width = max([m.right for m in ms])
		height = max([m.bottom for m in ms])

		extraWidth = -min([m.left for m in ms])
		extraHeight = -min([m.top for m in ms])

		width += extraWidth
		height += extraHeight

		hOff = width
		redo = []

		for m in leftMonitors:
			m.wLeft = width + m.left
			if m in bottomMonitors:
				continue
			m.right = width

		for m in topMonitors:
			m.wTop = height + m.top
			if m in rightMonitors:
				continue

			m.bottom = height

		return (width, height)	

	def setMonitorExtents(self):
		"""
		Set the monitor sizes, and posititions
		"""
		self.monitors = getMonitors()
		self.wSize = self.calcWallSize()
		sz = (0, 0, self.wSize[0], self.wSize[1])
		self._masterMonitor = Monitor(-1, sz, sz, 0, 0)

	def createEmptyWallpaper(self):
		"""
		Create an image representing the entire desktop
		"""

		c = (0, 0, 0, 0)
		StackMode = self.StackMode or any(m.StackMode for m in self.monitors)
		self.bgColour = c
		self.bgImage = bgImage = Image.new('RGBA', self.wSize, c)

		if StackMode:
			self.loadCurrentWallpaper()
		else:
			if self.Gradient:
				r, g, b = c
				width, height = bgImage.size
				fh = float(height)

				if (r + g + b) / 3 < 64:
					r1, g1, b1 = (128, 128, 128)
				else:
					r1, g1, b1 = c
					r, g, b = (64, 64, 64)

				rd = r1 - r
				gd = g1 - g
				bd = b1 - b

				rs = float(rd) / fh
				gs = float(gd) / fh
				bs = float(bd) / fh

				draw = ImageDraw.Draw(bgImage)
				for h in xrange(0, height):
					draw.line((0, h, width, h),
							  fill = (int(r1), int(g1), int(b1)))
					r1 -= rs
					b1 -= bs
					g1 -= gs	

	def generateWallpaper(self):
		"""
		Generate a wallpaper, by telling each monitor to generate its
		wallpaper with its own settings. Assign a thread per monitor,
		so that monitors are done in parallel.
		"""
		threads = []
		monitors = self.monitors if not self.Spanning else [self._masterMonitor,]
		for m in monitors:
			m.setMonitorConfig(self.config)
			m.setBgImage(self.bgImage)
			t = threading.Thread(target = m.generateWallpaper)
			threads.append(t)

		for t in threads: t.start()
		for t in threads: t.join()
		self.setWallpaper()
